package org.metasketch.editor.links;

import java.util.ArrayList;
import java.util.List;

import org.metasketch.diagram.javafx.graphics.BaseGraphic;

public class SemanticLink implements ILink {

	SemanticConfig semanticConfig = null;

	List<SemanticLinkConfig> semanticLinkConfigs = new ArrayList<SemanticLinkConfig>();

	String style;

	public SemanticEndConfig isPossibleFromSemanticType(Class type) {

		if (semanticLinkConfigs.size() == 0)
			return new SemanticEndConfig();

		SemanticEndConfig temp = null;
		for (SemanticLinkConfig linkConfig : semanticLinkConfigs) {
			temp = linkConfig.isSourceOrTarget(type);
			if (temp != null)
				return temp;
		}

		return null;

	}

	public EndType getEndType(Object source, Object target) {
		return getFinishEndTypeFromSemanticType((Class) source, (Class) target);
	}

	public EndType getFinishEndTypeFromSemanticType(Class startType,
			Class finishType) {

		if (semanticLinkConfigs.size() == 0)
			return EndType.TARGET;

		EndType endType = null;

		for (SemanticLinkConfig linkConfig : semanticLinkConfigs) {
			endType = linkConfig.getFinishEndType(startType, finishType);

			if (endType != null)
				return endType;
		}
		return null;

	}

	public EndType getStrictFinishEndTypeFromSemanticType(Class startType,
			Class finishType) {

		if (semanticLinkConfigs.size() == 0)
			return EndType.TARGET;

		EndType endType = null;

		for (SemanticLinkConfig linkConfig : semanticLinkConfigs) {
			endType = linkConfig.getStrictFinishEndType(startType, finishType);
			if (endType != null)
				return endType;
		}
		return null;

	}

	public EndType getProperFinishEndTypeFromSemanticType(Class startType,
			Class finishType) {

		EndType endType = null;
		endType = getStrictFinishEndTypeFromSemanticType(startType, finishType);

		if (endType == null)
			endType = getFinishEndTypeFromSemanticType(startType, finishType);

		return endType;
	}

	public SemanticLinkConfig getLinkConfigFromSemanticType(Class startType,
			Class finishType) {

		if (semanticLinkConfigs.size() == 0)
			return null;

		// EndType endType = null;

		for (SemanticLinkConfig linkConfig : semanticLinkConfigs) {
			if (!linkConfig.isInherited()) {
				if (linkConfig.getSource().getTypes().contains(startType)
						&& linkConfig.getTarget().getTypes()
								.contains(finishType))
					return linkConfig;
			} else {
				boolean found = false;
				for (Class iterType : linkConfig.getSource().getTypes()) {
					if (iterType.isAssignableFrom(startType)) {
						found = true;
						break;
					}
				}

				if (!found)
					return null;

				for (Class iterType : linkConfig.getTarget().getTypes()) {
					if (iterType.isAssignableFrom(finishType))
						return linkConfig;
				}

				return null;
			}
		}
		return null;

	}

	public String getStyle() {
		return style;
	}

	public void setStyle(String style) {
		this.style = style;
	}

	public SemanticConfig getSemanticConfig() {
		return semanticConfig;
	}

	public void setSemanticConfig(SemanticConfig semanticConfig) {
		this.semanticConfig = semanticConfig;
	}

	public List<SemanticLinkConfig> getSemanticLinkConfigs() {
		return semanticLinkConfigs;
	}

	public void setSemanticLinkConfigs(
			List<SemanticLinkConfig> semanticLinkConfigs) {
		this.semanticLinkConfigs = semanticLinkConfigs;
	}

	@Override
	public BaseEndConfig isPossible(BaseGraphic source) {

		if (source == null)
			return isPossibleFromSemanticType(null);
		else
			return isPossibleFromSemanticType(source.getSemantic().getClass());
	}

	@Override
	public EndType getFinishEndType(BaseGraphic source, BaseGraphic target) {
		Class sourceType = null;
		Class targetType = null;

		if (source != null)
			sourceType = source.getSemantic().getClass();

		if (target != null)
			targetType = target.getSemantic().getClass();

		return getFinishEndTypeFromSemanticType(sourceType, targetType);
	}

	@Override
	public EndType getStrictFinishEndType(BaseGraphic source, BaseGraphic target) {
		Class sourceType = null;
		Class targetType = null;

		if (source != null)
			sourceType = source.getSemantic().getClass();

		if (target != null)
			targetType = target.getSemantic().getClass();

		return getStrictFinishEndTypeFromSemanticType(sourceType, targetType);
	}

	@Override
	public EndType getProperFinishEndType(BaseGraphic source, BaseGraphic target) {
		Class sourceType = null;
		Class targetType = null;

		if (source != null)
			sourceType = source.getSemantic().getClass();

		if (target != null)
			targetType = target.getSemantic().getClass();

		return getProperFinishEndTypeFromSemanticType(sourceType, targetType);
	}

	@Override
	public SemanticLinkConfig getLinkConfig(BaseGraphic source,
			BaseGraphic target) {
		Class sourceType = null;
		Class targetType = null;

		if (source != null)
			sourceType = source.getSemantic().getClass();

		if (target != null)
			targetType = target.getSemantic().getClass();

		return getLinkConfigFromSemanticType(sourceType, targetType);
	}

}
